import logging
from abc import ABC, abstractmethod
import re

from check import Check
from transform import Transform


class SqlOperation(ABC):
    @abstractmethod
    def apply(self, sql_text: str, log_info: bool = True) -> tuple[str, str]:
        pass


class SqlCheck(SqlOperation):
    def __init__(self, rule_name, error_message, logger, reflect=False, regex_pattern=None):
        self.rule_name = rule_name
        self.regex_pattern = regex_pattern
        self.error_message = error_message
        self.logger = logger
        self.reflect = reflect

    def apply(self, sql_text: str, log_info: bool = True) -> tuple[str, str]:
        if not self.reflect:  ## 正则校验
            flag = not re.compile(self.regex_pattern, re.IGNORECASE).search(sql_text)
        else:  ## 反射校验
            flag = Check(sql_text, rule_name=self.rule_name).messages()

        if flag:
            if log_info:
                self.logger.info(f"{self.rule_name} Check passed: {self.error_message}")
            return sql_text, ""
        else:
            if not self.reflect:
                self.logger.error(
                    f"{self.rule_name} Check failed: {self.error_message} 位置坐标 {re.compile(self.regex_pattern, re.IGNORECASE).search(sql_text)}")
            else:
                self.logger.error(
                    f"{self.rule_name} Check failed: {self.error_message} ")
            return sql_text, self.error_message


class SqlTransform(SqlOperation):
    def __init__(self, rule_name, regex_pattern=None, replacement=None, logger=None, reflect=False,
                 db_name_config=None):
        self.rule_name = rule_name
        self.regex_pattern = regex_pattern
        self.replacement = replacement
        self.logger = logger
        self.reflect = reflect
        self.db_name_config = db_name_config

    def apply(self, sql_text: str, log_info: bool = True) -> tuple[str, str]:
        if not self.reflect:  ## 正则替换
            transformed_text = re.compile(self.regex_pattern, re.IGNORECASE).sub(self.replacement, sql_text)
        else:  ## 反射逻辑
            transformed_text = Transform(sql_text, rule_name=self.rule_name,db_name_config = self.db_name_config ).messages()
        if transformed_text != sql_text:
            if log_info:
                self.logger.info(f"{self.rule_name} Transformation applied: {self.regex_pattern} -> {self.replacement}")
            return transformed_text, ""
        else:
            if log_info:
                self.logger.info(f"{self.rule_name} No transformation needed for: {self.regex_pattern}")
            return sql_text, ""


class SqlPipelineBuilder:
    def __init__(self):
        self.operations = []

    def add_operation(self, operation: SqlOperation):
        self.operations.append(operation)
        return self

    def build(self):
        return SqlPipeline(self.operations)


class SqlPipeline:
    def __init__(self, operations):
        self.operations = operations
        self.logger = logging.getLogger('SqlPipeline')

    def execute(self, sql_text: str) -> tuple[str, list[str]]:
        failed_checks = []
        for operation in self.operations:
            sql_text, error = operation.apply(sql_text)
            if error:
                failed_checks.append(error)
            else:
                # 如果是替换操作，更新sql_text
                if isinstance(operation, SqlTransform):
                    sql_text = sql_text
        return sql_text, failed_checks
